home *** CD-ROM | disk | FTP | other *** search
/ Hot Super Models / Hot Super Models.iso / unix / x11 / xv200.tar / xv-2.00 / xvscrl.c < prev    next >
C/C++ Source or Header  |  1992-01-02  |  10KB  |  370 lines

  1. /* 
  2.  * xvscrl.c - Scroll Bar handling functions
  3.  *
  4.  * callable functions:
  5.  *
  6.  *   SCCreate()   -  creates the Scroll Bar window.
  7.  *   SCSetRange() -  sets min/max/current values of control
  8.  *   SCSetVal()   -  sets value of control 
  9.  *   SCRedraw()   -  redraws scroll bar
  10.  *   SCTrack()    -  called when clicked.  Operates control 'til mouseup
  11.  */
  12.  
  13. /*
  14.  * Copyright 1989, 1990, 1991, 1992 by John Bradley and
  15.  *                       The University of Pennsylvania
  16.  *
  17.  * Permission to use, copy, and distribute for non-commercial purposes,
  18.  * is hereby granted without fee, providing that the above copyright
  19.  * notice appear in all copies and that both the copyright notice and this
  20.  * permission notice appear in supporting documentation.
  21.  *
  22.  * The software may be modified for your own purposes, but modified versions
  23.  * may not be distributed.
  24.  *
  25.  * This software is provided "as is" without any expressed or implied warranty.
  26.  *
  27.  * The author may be contacted via:
  28.  *    US Mail:   John Bradley
  29.  *               GRASP Lab, Room 301C
  30.  *               3401 Walnut St.
  31.  *               Philadelphia, PA  19104
  32.  *
  33.  *    Phone:     (215) 898-8813
  34.  *    EMail:     bradley@cis.upenn.edu
  35.  */
  36.  
  37.  
  38. #include "xv.h"
  39. #include "bitmaps.h"
  40.  
  41.  
  42. static Pixmap upPix,  downPix;   /* up/down arrows */
  43. static Pixmap up1Pix, down1Pix;  /* up/down arrows (lit up) */
  44. static Pixmap sgray;             /* gray stipple for lit scrollbar */
  45. static int    pixmaps_built=0;   /* true if pixmaps created already */
  46.  
  47.  
  48. /* scroll regions */
  49. #define UPLINE 0
  50. #define UPPAGE 1
  51. #define DNLINE 2
  52. #define DNPAGE 3
  53. #define THUMB  4
  54.  
  55. #define SCRLWAIT 150   /* milliseconds to wait between scrolls */
  56.  
  57. /* local functions */
  58. #ifdef __STDC__
  59. static int  whereInScrl(SCRL *, int, int);
  60. static void drawArrow(SCRL *, int);
  61. #else
  62. static int  whereInScrl();
  63. static void drawArrow();
  64. #endif
  65.  
  66.  
  67. /***************************************************/
  68. void SCCreate(sp, parent, x, y, vert, len, minv, maxv, curv, page, 
  69.               fg, bg, func)
  70. SCRL         *sp;
  71. Window        parent;
  72. int           x,y,vert,len,minv,maxv,curv,page;
  73. unsigned long fg,bg;
  74. void          (*func)();
  75. {
  76.  
  77.  
  78.   if (!pixmaps_built) {
  79.     upPix    = XCreatePixmapFromBitmapData(theDisp, parent, 
  80.         up_bits, up_width, up_height, fg, bg, dispDEEP);
  81.     downPix  = XCreatePixmapFromBitmapData(theDisp, parent, 
  82.             down_bits, down_width, down_height, fg, bg, dispDEEP);
  83.     up1Pix   = XCreatePixmapFromBitmapData(theDisp, parent, 
  84.                 up1_bits, up1_width, up1_height, fg, bg, dispDEEP);
  85.     down1Pix = XCreatePixmapFromBitmapData(theDisp, parent, 
  86.             down1_bits, down1_width, down1_height,fg,bg,dispDEEP);
  87.     sgray    = XCreatePixmapFromBitmapData(theDisp, parent,
  88.             scrlgray_bits, scrlgray_width, scrlgray_height,fg,bg,dispDEEP);
  89.   }
  90.  
  91.   sp->vert = vert;
  92.   sp->len  = len;
  93.   sp->fg   = fg;
  94.   sp->bg   = bg;
  95.   sp->uplit = sp->dnlit = 0;
  96.  
  97.   if (vert) 
  98.     sp->win = XCreateSimpleWindow(theDisp, parent,x,y,up_width-2,len,1,fg,bg);
  99.   else FatalError("don't know HOW to make horizontal scrollbar");
  100.  
  101.   if (!sp->win) FatalError("can't create scrollbar window");
  102.  
  103.   sp->tsize  =  up_width-2;      /* really only if vertical */
  104.   sp->tmin   =  up_height-1;
  105.   sp->tmax   =  len - (up_height-1) - sp->tsize;
  106.   sp->drawobj = func;
  107.  
  108.   SCSetRange(sp, minv, maxv, curv, page);
  109.   XSelectInput(theDisp, sp->win, ExposureMask | ButtonPressMask);
  110. }
  111.  
  112.  
  113. /***************************************************/
  114. void SCSetRange(sp, minv, maxv, curv, page)
  115. SCRL *sp;
  116. int   minv, maxv, curv, page;
  117. {
  118.   if (maxv<minv) maxv=minv;
  119.   sp->min = minv;    sp->max = maxv;    sp->page = page;
  120.   sp->active =  (minv < maxv);
  121.  
  122.   /* adjust scroll bar background */
  123.   if (sp->active) XSetWindowBackgroundPixmap(theDisp, sp->win, sgray);
  124.              else XSetWindowBackground(theDisp, sp->win, sp->bg);
  125.  
  126.   sp->val = -99999;  /* force a redraw */
  127.   SCSetVal(sp, curv);
  128. }
  129.  
  130.  
  131. /***************************************************/
  132. int SCSetVal(sp, curv)
  133. SCRL *sp;
  134. int   curv;
  135. {
  136.   /* returns '0' if no redraw was done */
  137.  
  138.   RANGE(curv, sp->min, sp->max);   /* make sure curv is in-range */
  139.  
  140.   if (sp->val == curv) return 0;
  141.  
  142.   sp->val = curv;
  143.  
  144.   if (sp->active) 
  145.     sp->tpos = sp->tmin + ((sp->tmax - sp->tmin)*(curv - sp->min))
  146.                         / (sp->max - sp->min);
  147.   SCRedraw(sp);
  148.   (sp->drawobj)();     /* redraw whatever the scrollbar controls */
  149.   XFlush(theDisp);
  150.   return 1;
  151. }
  152.  
  153.  
  154. /***************************************************/
  155. void SCRedraw(sp)
  156. SCRL *sp;
  157. {
  158.   XSetForeground(theDisp, theGC, sp->fg);
  159.   XSetBackground(theDisp, theGC, sp->bg);
  160.  
  161.   XClearWindow(theDisp, sp->win);
  162.   
  163.   if (sp->vert) {    /* draw up/down arrows */
  164.     drawArrow(sp,UPLINE);
  165.     drawArrow(sp,DNLINE);
  166.  
  167.     if (sp->active) {   /* a thumb is necessary */
  168.       XSetForeground(theDisp, theGC, sp->bg);
  169.       XFillRectangle(theDisp, sp->win, theGC,
  170.              1, sp->tpos+1, sp->tsize-2, sp->tsize-2);
  171.       XSetForeground(theDisp, theGC, sp->fg);
  172.       XDrawRectangle(theDisp, sp->win, theGC,
  173.              0, sp->tpos, sp->tsize-1, sp->tsize-1);
  174.     }
  175.   }
  176. }
  177.  
  178.  
  179.  
  180. /***************************************************/
  181. static int whereInScrl(sp,x,y)
  182. SCRL *sp;
  183. int x,y;
  184. {
  185.   int v;
  186.  
  187.   /* returns region # that x,y is in.  Returns '-1' if none */
  188.  
  189.   v=0;
  190.   if (sp->vert) {
  191.     if (x<0 || x>up_width-2 || y<0 || y>sp->len) return -1;
  192.     v = y;
  193.   }
  194.  
  195.   /* once we know it's in scroll bar, only have to check 'v' versus len */
  196.   if (v < sp->tmin)               return UPLINE;
  197.   if (sp->active) {
  198.     if (v <  sp->tpos)             return UPPAGE;
  199.     if (v <  sp->tpos + sp->tsize) return THUMB;
  200.     if (v <= sp->tmax + sp->tsize) return DNPAGE;
  201.   }
  202.   if (v > sp->tmax+sp->tsize)    return DNLINE;
  203.  
  204.   return -1;
  205. }
  206.  
  207.  
  208. /***************************************************/
  209. static void drawArrow(sp,arr)
  210. SCRL *sp;
  211. int arr;
  212. {
  213.   /* only if vertical */
  214.   if (arr == UPLINE) {
  215.     if (sp->uplit) 
  216.       XCopyArea(theDisp, up1Pix,  sp->win,theGC,0,0,up_width,up_height,-1,-1);
  217.     else
  218.       XCopyArea(theDisp, upPix,   sp->win,theGC,0,0,up_width,up_height,-1,-1);
  219.   }
  220.  
  221.   else if (arr == DNLINE) {
  222.     if (sp->dnlit) 
  223.       XCopyArea(theDisp, down1Pix,sp->win,theGC,0,0,up_width,up_height,
  224.         -1, sp->len-(up_height-1));
  225.     else
  226.       XCopyArea(theDisp, downPix, sp->win,theGC,0,0,up_width,up_height,
  227.         -1, sp->len-(up_height-1));
  228.   }
  229.  
  230.   XFlush(theDisp);
  231. }
  232.  
  233.  
  234. /***************************************************/
  235. void SCTrack(sp,mx,my)
  236. SCRL *sp;
  237. int mx,my;
  238. {
  239.   Window       rW,cW;
  240.   int          rx,ry, x,y, ipos, pos, lit, ty, tyoff, ty1;
  241.   unsigned int mask;
  242.  
  243.   /* determine in which of the five regions of the scroll bar the mouse
  244.      was clicked (upline, downline, uppage, downpage, thumb) */
  245.  
  246.   ty = tyoff = 0;
  247.  
  248.   XSetForeground(theDisp, theGC, sp->fg);
  249.   XSetBackground(theDisp, theGC, sp->bg);
  250.  
  251.   /* light up appropriate bit of scroll bar */
  252.   ipos = whereInScrl(sp,mx,my);
  253.   lit = 1;
  254.  
  255.   switch (ipos) {
  256.   case UPLINE:  sp->uplit = 1;
  257.                 if (sp->val > sp->min) SCSetVal(sp,sp->val-1);                
  258.                 Timer(SCRLWAIT);
  259.                 break;
  260.  
  261.   case DNLINE:  sp->dnlit = 1;
  262.                 if (sp->val < sp->max) SCSetVal(sp,sp->val+1);
  263.                 Timer(SCRLWAIT);
  264.                 break;
  265.  
  266.   case UPPAGE:  SCSetVal(sp,sp->val - sp->page);  break;
  267.   case DNPAGE:  SCSetVal(sp,sp->val + sp->page);  break;
  268.   case THUMB:   tyoff = sp->tpos - my;
  269.                 ty = sp->tpos;
  270.                 XSetState(theDisp, theGC, sp->fg, sp->bg, GXinvert, 
  271.               sp->fg ^ sp->bg);
  272.                 XDrawRectangle(theDisp,sp->win,theGC,
  273.                    0, sp->tpos, sp->tsize-1, sp->tsize-1);
  274.                 break;
  275.   }
  276.  
  277.   /* VERTICAL CODE ONLY */
  278.   while (XQueryPointer(theDisp,sp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
  279.     if (!(mask & Button1Mask)) break;    /* button released */
  280.  
  281.     switch (ipos) {
  282.  
  283.     case THUMB:
  284.       /* do thumb tracking */
  285.       if (x<-16 || x>16+sp->tsize) {   /* outside tracking range */
  286.     if (lit) {
  287.       lit = 0;
  288.       XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
  289.     }
  290.       }
  291.  
  292.       else {                           /* inside tracking range */
  293.     if (!lit) {  /* not lit, just turn on */
  294.       lit = 1;
  295.       ty = y + tyoff;
  296.       RANGE(ty, sp->tmin, sp->tmax);
  297.       XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
  298.     }
  299.     else { /* already lit, more the thumb */
  300.       ty1 = y+tyoff;
  301.       RANGE(ty1, sp->tmin, sp->tmax);
  302.       if (ty != ty1) {    /* but only if mouse has moved */
  303.         XDrawRectangle(theDisp, sp->win, theGC, 
  304.                0,ty,sp->tsize-1,sp->tsize-1);
  305.         ty = ty1;
  306.         XDrawRectangle(theDisp, sp->win, theGC, 
  307.                0,ty,sp->tsize-1,sp->tsize-1);
  308.       }
  309.     }
  310.       }
  311.       break;
  312.  
  313.  
  314.     case UPLINE:
  315.     case DNLINE:                     /* arrows */
  316.       pos = whereInScrl(sp,x,y);
  317.       if (pos == ipos) {
  318.     if (!lit) { 
  319.       lit = 1; 
  320.       if (ipos == UPLINE) { sp->uplit = 1;  drawArrow(sp,UPLINE); }
  321.                      else { sp->dnlit = 1;  drawArrow(sp,DNLINE); }
  322.     }
  323.  
  324.     else {
  325.       if (sp->val > sp->min && pos==UPLINE) {
  326.         SCSetVal(sp, sp->val-1);
  327.         Timer(SCRLWAIT);
  328.       }
  329.       else if (sp->val < sp->max && pos==DNLINE) {
  330.         SCSetVal(sp, sp->val+1);
  331.         Timer(SCRLWAIT);
  332.       }
  333.     }
  334.       }
  335.       
  336.       else {
  337.     if (lit) { 
  338.       lit = 0; 
  339.       if (ipos == UPLINE) { sp->uplit = 0;  drawArrow(sp,UPLINE); }
  340.                      else { sp->dnlit = 0;  drawArrow(sp,DNLINE); }
  341.     }
  342.       }
  343.       break;
  344.       
  345.     }
  346.   }
  347.  
  348.  
  349.   if (ipos == THUMB) {
  350.     if (lit)    /* turn off */
  351.       XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
  352.  
  353.     XSetState(theDisp, theGC, sp->fg, sp->bg, GXcopy, AllPlanes);
  354.  
  355.     if (lit && ty != sp->tpos) {    /* if thumb was moved, ROUND to new val */
  356.       int dt, dv;
  357.       dt = sp->tmax - sp->tmin;
  358.       dv = sp->max  - sp->min;
  359.       SCSetVal(sp, sp->min + (dv*(ty - sp->tmin)+dt/2) / dt);
  360.     }
  361.   }
  362.  
  363.   if (lit && ipos == UPLINE) { sp->uplit = 0; drawArrow(sp, UPLINE); }
  364.   if (lit && ipos == DNLINE) { sp->dnlit = 0; drawArrow(sp, DNLINE); }
  365. }
  366.  
  367.  
  368.  
  369.  
  370.